package com.ysdz.tibetan.tibetanmini.security.service;//package com.zy.springsecurityoauth2.service.security;

import com.alibaba.fastjson.JSONObject;
import com.ysdz.tibetan.tibetanmini.security.beans.ConsumerDetails;
import com.ysdz.tibetan.tibetanmini.user.beans.Consumer;
import com.ysdz.tibetan.tibetanmini.user.beans.Role;
import com.ysdz.tibetan.tibetanmini.user.beans.UserRole;
import com.ysdz.tibetan.tibetanmini.user.dao.UsersMapper;
import com.ysdz.tibetan.tibetanmini.user.service.ConsumerService;
import com.ysdz.tibetan.tibetanmini.user.service.UserRoleService;
import com.ysdz.tibetan.tibetanmini.wechat.entity.WxMessage;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import java.net.URI;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;

/**
 * @description 用户名:openId 密码:appId 自动注册为普通用户
 */
@Service
public class UserDetailServiceImpl implements UserDetailsService {

    @Autowired
    private ConsumerService consumerService;

    @Autowired
    private UsersMapper usersMapper;

    @Autowired
    private UserRoleService userRoleService;

    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;

    @Autowired
    private RestTemplate restTemplate;

    @Value("${wx.applet.appId}")
    private String appId;

    @Value("${wx.applet.appSecret}")
    private String appSecret;

    private static final String WX_API = "https://api.weixin.qq.com/sns/jscode2session";

    /**
     * 根据 code查 openId 再通过 openId 查出用户
     *
     * @param code 微信凭证（用来获取openId）
     * @return 用户详细信息
     */
    @Override
    public UserDetails loadUserByUsername(String code) throws UsernameNotFoundException {
        //标识身份
        boolean flag = true;
        //获取openId
        String username = this.getOpenId(code);

        //如果 openId 为 null 则表示为管理员登录
        if (Objects.isNull(username)){
            //这里的 code 就是管理员的用户名
            username = code;
            flag = false;
        }

        Consumer consumer = consumerService.findUserByUsername(username);

        //微信用户 && 第一次登陆  加入信息到数据库
        if (Objects.isNull(consumer) && flag) {
            consumer = new Consumer();
            //自动注册一个用户
            consumer.setUsername(username);
            consumer.setPassword(bCryptPasswordEncoder.encode(appId));
            usersMapper.insertUseGeneratedKeys(consumer);
            // 注册普通用户  /  需要重查 拿取 userId
            consumer = consumerService.findUserByUsername(username);
            UserRole userRole = new UserRole();
            userRole.setUserId(consumer.getUserId());
            userRole.setRoleId(2L);
            userRoleService.save(userRole);
        }

        ConsumerDetails consumerDetails = new ConsumerDetails();
        BeanUtils.copyProperties(consumer, consumerDetails);

        Set<GrantedAuthority> authorities = new HashSet<>();    // 角色集合

        List<Role> roleList = consumerService.findRoleByUserId(consumerDetails.getUserId());
        roleList.forEach(role -> {
            authorities.add(new SimpleGrantedAuthority("ROLE_" + role.getRoleName()));
        });
        consumerDetails.setAuthorities(authorities);
        return consumerDetails;
    }

    private String getOpenId(String code) {
        MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
        params.add("appid", appId);
        params.add("secret", appSecret);
        params.add("js_code", code);
        params.add("grant_type", "authorization_code");
        URI code2Session = getURIWithParams(WX_API, params);
        String wxMessage = restTemplate.exchange(code2Session, HttpMethod.GET, new HttpEntity<String>(new HttpHeaders()), String.class).getBody();
        WxMessage message = JSONObject.parseObject(wxMessage, WxMessage.class);
        return message.getOpenid();
    }

    private URI getURIWithParams(String url, MultiValueMap<String, String> params) {
        UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url).queryParams(params);
        return builder.build().encode().toUri();
    }
}
